import json
import logging
import signal
import sys
import tkinter as tk
from tkinter import filedialog, messagebox, ttk

logger = logging.getLogger(__name__)


class BaseWindow:
    """基础窗体类"""

    def __init__(self):
        self.window = tk.Tk()
        self.window.title("Data Shadow-数据影子对比工具")
        self.window.geometry("1200x800")
        self.window.minsize(1200, 800)

        # 初始化成员变量
        self.source1 = None
        self.source2 = None
        self.id_fields = []
        self.data_fields = []

        # 保存对 self 的引用
        self.window.app = self

        # 绑定窗口关闭事件
        self.window.protocol("WM_DELETE_WINDOW", self._on_closing)

        # 设置信号处理
        self._setup_signal_handlers()

    def _setup_signal_handlers(self):
        """设置信号处理器"""

        def signal_handler(signum, frame):
            logger.info(f"收到信号: {signum}")
            self.quit()

        # 注册 SIGINT (Ctrl+C) 处理器
        try:
            signal.signal(signal.SIGINT, signal_handler)
            # 在 Windows 上额外处理 SIGBREAK
            if sys.platform == "win32":
                signal.signal(signal.SIGBREAK, signal_handler)
        except (AttributeError, ValueError) as e:
            logger.warning(f"无法设置信号处理器: {e}")

    def _init_ui(self):
        """初始化UI布局"""
        raise NotImplementedError

    def _on_closing(self):
        """窗口关闭时的处理函数"""
        if messagebox.askokcancel("确认退出", "确定要退出程序吗？"):
            self.quit()

    def quit(self):
        """安全退出程序"""
        try:
            # 执行清理操作
            self._cleanup()
            # 销毁窗口
            self.window.quit()
            self.window.destroy()
        except Exception as e:
            logger.error(f"退出时发生错误: {e}")
            sys.exit(1)
        else:
            sys.exit(0)

    def _cleanup(self):
        """执行清理操作"""
        # 关闭数据库连接等资源
        if hasattr(self, "source1") and self.source1:
            try:
                self.source1.close()
            except:
                pass
        if hasattr(self, "source2") and self.source2:
            try:
                self.source2.close()
            except:
                pass

    def run(self):
        """运行程序"""
        try:
            # 设置定期检查信号的任务
            def check_signals():
                self.window.after(100, check_signals)

            self.window.after(100, check_signals)

            # 启动主循环
            self.window.mainloop()
        except KeyboardInterrupt:
            logger.info("程序被用户中断")
            self.quit()
        except Exception as e:
            logger.error(f"程序运行时发生错误: {e}")
            self.quit()

    def _save_config(self):
        """保存配置"""
        try:
            config_data = {
                "fields": [field.to_dict() for field in self.fields],
                "id_fields": self.id_fields,
                "source1": self.source1.to_dict() if self.source1 else None,
                "source2": self.source2.to_dict() if self.source2 else None,
            }

            # 如果是数据库类型，确保保存数据库配置
            if self.source1 and self.source1.type == SourceType.DATABASE:
                config_data["source1"]["db_config"] = self.source1.db_config
            if self.source2 and self.source2.type == SourceType.DATABASE:
                config_data["source2"]["db_config"] = self.source2.db_config

            file_path = filedialog.asksaveasfilename(
                defaultextension=".json",
                filetypes=[("JSON files", "*.json")],
                title="保存配置",
            )
            if file_path:
                with open(file_path, "w", encoding="utf-8") as f:
                    json.dump(config_data, f, ensure_ascii=False, indent=2)
                logger.info(f"配置已保存到: {file_path}")
                messagebox.showinfo("成功", "配置已保存")

        except Exception as e:
            logger.error(f"保存配置失败: {str(e)}", exc_info=True)
            messagebox.showerror("错误", f"保存失败: {str(e)}")

    def _load_config(self):
        """加载配置"""
        try:
            file_path = filedialog.askopenfilename(
                filetypes=[("JSON files", "*.json")], title="加载配置"
            )
            if file_path:
                with open(file_path, "r", encoding="utf-8") as f:
                    config_data = json.load(f)

                # 加载数据项
                self.fields = [
                    Field.from_dict(field) for field in config_data["fields"]
                ]
                self.id_fields = config_data["id_fields"]

                # 加载数据源配置
                if config_data.get("source1"):
                    self.source1 = DataSource.from_dict(config_data["source1"])
                if config_data.get("source2"):
                    self.source2 = DataSource.from_dict(config_data["source2"])

                # 更新界面
                self._update_ui()
                logger.info(f"成功导入数据项: {file_path}")

        except Exception as e:
            logger.error(f"加载配置失败: {str(e)}", exc_info=True)
            messagebox.showerror("错误", f"加载失败: {str(e)}")

    def center_dialog(self, dialog):
        """使对话框居中显示"""
        # 等待对话框完全初始化
        dialog.update_idletasks()

        # 获取父窗口和对话框的尺寸
        dialog_width = dialog.winfo_width()
        dialog_height = dialog.winfo_height()
        parent_x = self.window.winfo_x()
        parent_y = self.window.winfo_y()
        parent_width = self.window.winfo_width()
        parent_height = self.window.winfo_height()

        # 计算居中位置
        x = parent_x + (parent_width - dialog_width) // 2
        y = parent_y + (parent_height - dialog_height) // 2

        # 设置对话框位置
        dialog.geometry(f"+{x}+{y}")
